/**
 * 节点工厂类
 * 负责创建和管理工作流节点
 */
import {componentRegistry, WORKFLOW_STYLE_DEFAULTS} from './ComponentRegistry'

class NodeFactory {
    /**
     * 创建节点实例
     * @param {string} type - 节点类型（如 'start'、'activity'、'condition'、'loop' 等）
     * @param {Object} data - 节点业务数据；泳道可设置 headerHeight/innerPadding
     * @param {Object} graph - X6 图形实例
     * @returns {Object} X6 节点实例
     *
     * 主要属性含义：
     * - shape：渲染形状，默认 'rect'；泳道为矩形
     * - x/y：初始位置（画布坐标）
     * - width/height：节点尺寸
     * - label：显示名称，默认取注册配置的 defaultName
     * - draggable：是否可拖拽
     * - data：业务数据（type、code 等），泳道包含：
     *   - headerHeight：标题栏高度（默认 30）
     *   - innerPadding：内容区内边距（默认 8）
     * - markup：渲染结构定义；泳道为 [body, name-rect, name-text]
     * - attrs：外观样式；body 为主体、name-rect 为标题栏矩形、name-text 为标题文字
     * - ports：连接端口；泳道不提供端口，普通节点提供四方向端口
     */
    createNode(type, data = {}, graph) {
        const config = componentRegistry.getNodeConfig(type)
        if (!config) {
            throw new Error(`未找到节点类型: ${type}`)
        }

        const nodeConfig = {
            id: data.id || `node_${Date.now()}`,
            shape: config.shape || 'rect',
            x: data.x || 100,
            y: data.y || 100,
            width: config.width || 140,
            height: config.height || 80,
            label: data.name || config.defaultName,
            // 启用节点拖拽功能
            draggable: true,
            data: type === 'loop' ? {
                ...data,
                type: type,
                code: data.code || `${type}_${Date.now()}`,
                headerHeight: data.headerHeight ?? WORKFLOW_STYLE_DEFAULTS.loop.headerHeight,
                innerPadding: data.innerPadding ?? WORKFLOW_STYLE_DEFAULTS.loop.innerPadding
            } : {
                ...data,
                type: type,
                code: data.code || `${type}_${Date.now()}`
            },
            // 根据节点类型使用不同的markup配置
            markup: config.markup || (type === 'loop' ? [
                {tagName: 'rect', selector: 'body'},
                {tagName: 'rect', selector: 'name-rect'},
                {tagName: 'text', selector: 'name-icon'},
                {tagName: 'text', selector: 'name-text'}
            ] : [
                {tagName: 'rect', selector: 'body'},
                {tagName: 'rect', selector: 'iconRect'},
                {tagName: 'text', selector: 'icon'},
                {tagName: 'text', selector: 'label'}
            ]),
            attrs: type === 'loop' ? {
                body: {
                    stroke: config.stroke || 'rgb(137, 210, 178)',
                    fill: 'rgba(255,255,255,0.1)',
                    rx: WORKFLOW_STYLE_DEFAULTS.loop.cornerRadius,
                    ry: WORKFLOW_STYLE_DEFAULTS.loop.cornerRadius
                },
                'name-rect': config.attrs?.['name-rect'] || {
                    refWidth: ((config.width - 4) / config.width) *100 + '%',
                    height: WORKFLOW_STYLE_DEFAULTS.loop.headerHeight,
                    refY: 2,
                    refX: 2,
                    fill: '#FFFFFF',
                    stroke: 'transparent',
                    rx: WORKFLOW_STYLE_DEFAULTS.loop.cornerRadius,
                    ry: WORKFLOW_STYLE_DEFAULTS.loop.cornerRadius
                },
                'name-icon': config.attrs?.['name-icon'] || {
                    text: (data.iconUnicode ?? config.iconUnicode ?? ''),
                    ref: 'name-rect',
                    refY: 0.5,
                    refX: 12,
                    fontFamily: 'iconfont',
                    fontSize: (WORKFLOW_STYLE_DEFAULTS.label.fontSize + 6),
                    fill: (data.color ?? config.color ?? '#333333'),
                    textVerticalAnchor: 'middle',
                    textAnchor: 'start'
                },
                'name-text': config.attrs?.['name-text'] || {
                    text: (data.name || config.defaultName || '循环'),
                    ref: 'name-rect',
                    refY: 0.5,
                    refX: 40,
                    textAnchor: 'start',
                    fontWeight: 'bold',
                    fill: '#333333',
                    fontSize: WORKFLOW_STYLE_DEFAULTS.label.fontSize,
                    textVerticalAnchor: 'middle'
                }
            } : {
                body: {
                    stroke: config.stroke || 'rgb(137, 210, 178)',
                    fill: '#FFFFFF',
                    rx: config.rx || 6,
                    ry: config.ry || 6
                },
                label: {
                    fontSize: WORKFLOW_STYLE_DEFAULTS.label.fontSize,
                    fontWeight: WORKFLOW_STYLE_DEFAULTS.label.fontWeight,
                    fill: config.labelColor || '#333333',
                    refX: 36,
                    refY: 11,
                    textAnchor: 'start',
                    textVerticalAnchor: 'top'
                },
                icon: {
                    text: (data.iconUnicode ?? config.iconUnicode ?? ''),
                    fontFamily: 'iconfont',
                    fontSize: (WORKFLOW_STYLE_DEFAULTS.label.fontSize + 8),
                    fill: (data.color ?? config.color ?? '#333333'),
                    refX: 6,
                    refY: 6,
                    textAnchor: 'start',
                    textVerticalAnchor: 'top'
                }
            },
            // 为所有节点提供端口；若无自定义 ports，则使用默认
            ports: config.ports || {
                groups: {
                    top: {
                        position: 'top',
                        attrs: {
                            circle: {...WORKFLOW_STYLE_DEFAULTS.portDot}
                        }
                    },
                    right: {
                        position: 'right',
                        attrs: {
                            circle: {...WORKFLOW_STYLE_DEFAULTS.portDot}
                        }
                    },
                    bottom: {
                        position: 'bottom',
                        attrs: {
                            circle: {...WORKFLOW_STYLE_DEFAULTS.portDot}
                        }
                    },
                    left: {
                        position: 'left',
                        attrs: {
                            circle: {...WORKFLOW_STYLE_DEFAULTS.portDot}
                        }
                    }
                },
                items: [
                    {group: 'top'},
                    {group: 'right'},
                    {group: 'bottom'},
                    {group: 'left'}
                ]
            }
        }

        // 应用自定义样式
        if (config.customStyle) {
            Object.assign(nodeConfig.attrs, config.customStyle)
        }

        return graph.createNode(nodeConfig)
    }

    /**
     * 更新节点数据
     * @param {Object} node - 节点实例
     * @param {Object} newData - 新数据（与已有数据合并）
     * @returns {void}
     *
     * 说明：当 newData 包含 name 时，同时更新节点的标签显示文字。
     */
    updateNodeData(node, newData) {
        const currentData = node.getData() || {}
        node.setData({...currentData, ...newData})

        // 更新标签
        if (newData.name) {
            const data = node.getData() || {}
            if (data.type === 'loop') {
                node.attr('name-text/text', newData.name)
            } else {
                node.attr('label/text', newData.name)
            }
        }
    }

    /**
     * 验证节点数据
     * @param {Object} node - 节点实例
     * @returns {Array<string>} 验证错误信息列表
     *
     * 说明：根据组件注册配置中的 requiredFields 校验必填项是否为空。
     */
    validateNode(node) {
        const errors = []
        const data = node.getData() || {}
        const config = componentRegistry.getNodeConfig(data.type)

        if (!config) {
            errors.push(`未知的节点类型: ${data.type}`)
            return errors
        }

        // 检查必填字段
        if (config.requiredFields) {
            config.requiredFields.forEach(field => {
                if (!data[field] || data[field].toString().trim() === '') {
                    errors.push(`${field} 是必填字段`)
                }
            })
        }

        return errors
    }

    /**
     * 获取节点默认配置
     * @param {string} type - 节点类型
     * @returns {Object} 默认配置对象（来自组件注册配置）
     */
    getDefaultConfig(type) {
        const config = componentRegistry.getNodeConfig(type)
        return config ? config.defaultConfig || {} : {}
    }
}

export const nodeFactory = new NodeFactory()

export default NodeFactory
